//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <fcntl.h>
#include <string.h>
#include <linux/param.h>
#include <aura.h>
#include <aura_wchar.h>
#include "private.h"

extern struct timeval g_tvStartTime;

AURA_API AuraSystem_GetTime(
        /* [out] */ Aura_SystemTime * pTime)
{
    struct timeval tv;
    int res = 0;

    assert(NULL != pTime);

    res = gettimeofday(&tv, NULL);
    if (res < 0) {
        goto E_FAIL_EXIT;
    }
    pTime->seconds = (Aura_Int32)tv.tv_sec;
    pTime->microseconds = (Aura_Int32)tv.tv_usec;

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraSystem_SetTime(
        /* [in] */ Aura_SystemTime * pTime)
{
    struct timeval tv;
    int res = 0;

    assert(NULL != pTime);

    tv.tv_sec  = (time_t)pTime->seconds;
    tv.tv_usec = (suseconds_t)pTime->microseconds;

    res = settimeofday(&tv, NULL);
    if (res < 0) {
        goto E_FAIL_EXIT;
    }
    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraSystem_QueryPerformanceCounter(
        /* [out] */Aura_Int64 * pCounter)
{
    FixMe("Not implemented yet.");
    return AURA_E_NOT_IMPLEMENTED;
}

AURA_API AuraSystem_QueryPerformanceFrequency(
        /* [out] */Aura_Int64 * pFrequency)
{
    FixMe("Not implemented yet.");
    return AURA_E_NOT_IMPLEMENTED;
}

AURA_API AuraSystem_GetElapsedTime(
        /* [out] */ Aura_Millisecond32 * pTime)
{
    struct timeval current_time;

    assert(NULL != pTime);

    gettimeofday(&current_time, 0);

    *pTime = (current_time.tv_sec  - g_tvStartTime.tv_sec) * 1000 +
             (current_time.tv_usec - g_tvStartTime.tv_usec) / 1000;

    return AURA_NOERROR;
}

AURA_API AuraSystem_GetIdleTime(
        /* [out] */ Aura_Millisecond32 * pTime)
{
    FixMe("Not implemented yet.");
    return AURA_E_NOT_IMPLEMENTED;
}

AURA_API AuraSystem_GetMemorySizes(
        /* [out] */ Aura_Int32 * pTotalPhysicalMemorySize,
        /* [out] */ Aura_Int32 * pAvailablePhysicalMemorySize)
{
#ifndef _android  
    FILE *pFile = NULL;
    char *pNum  = NULL;
    char *pMemFreeLine  = NULL;
    char *pMemTotalLine = NULL;
    ssize_t readSize = 0;
    size_t bufferLen = 0;
    size_t nameLen = 0;
    Aura_UInt32 uTotalMem = 0;
    Aura_UInt32 uFreeMem  = 0;

    pFile = fopen("/proc/meminfo", "r");
    if(NULL == pFile){
        goto E_FAIL_EXIT;
    }

    readSize = getline(&pMemTotalLine, &bufferLen, pFile);
    if(-1 == readSize){
        goto E_FAIL_EXIT;
    }

    bufferLen =0;
    readSize = getline(&pMemFreeLine, &bufferLen, pFile);
    if(-1 == readSize){
        goto E_FAIL_EXIT;
    }

    fclose(pFile);

    nameLen = strlen("MemTotal:");
    pNum = pMemTotalLine + nameLen;
    while(' ' == *pNum) {
        pNum++;
    }
    uTotalMem = atoi(pNum);

    nameLen = strlen("MemFree:");
    pNum = pMemFreeLine + nameLen;
    while(' ' == *pNum) {
        pNum++;
    }
    uFreeMem = atoi(pNum);

    if(NULL != pTotalPhysicalMemorySize){
        *pTotalPhysicalMemorySize = (Aura_Int32)uTotalMem;
    }
    if(NULL != pAvailablePhysicalMemorySize){
        *pAvailablePhysicalMemorySize = (Aura_Int32)uFreeMem;
    }

    free(pMemTotalLine);
    free(pMemFreeLine);

    return AURA_NOERROR;

E_FAIL_EXIT:
    if(NULL != pFile) {
        fclose(pFile);
    }
    if(NULL != pMemTotalLine) {
        free(pMemTotalLine);
    }
    if(NULL != pMemFreeLine) {
        free(pMemFreeLine);
    }

    return GetLastAuraECode();
#endif
    return AURA_E_NOT_IMPLEMENTED;
}

AURA_API AuraSystem_ErrorPrint(
        /* [in] */ Aura_PWChar wstr)
{
    assert(wstr && wstr[0] != 0);

    int len=Aura_Wcslen(wstr);
    wchar_t *lwstr = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
    if(!lwstr) return AURA_E_OUT_OF_MEMORY;
    Aura_PWchar_to_Pwchar_t(wstr,lwstr);
    wprintf(L"%S", lwstr);
    free (lwstr);
    return AURA_NOERROR;
}
